// OpentTxl-C Version 11 safe strings
// Copyright 2023, James R. Cordy and others

// Modification Log

// v11.0 Initial revision
// v11.3 Removed option for unsafe optimizations - never use strcpy, memcpy, memset, memmove

// TXL safe strings

// Safe C strings for use in OpenTxl
// This is a completely safe C implementation of strings.
// Provided that all strings are declared using the type "string" and only these operations are used, 
// safety is assured. Longstrings are strings with a 1 Mb length limit.

// All strings in OpenTxl are 1-origin and chars are [1 .. length]

#include <string.h>
#include <ctype.h>

// OpenTxl logic assumes these limits
#define maxStringLength         4095    // 4 kb - 1; limits TXL source code lines
#define maxLongStringLength     1048575 // 1 Mb - 1; limits target language source code lines

// All strings in OpenTxl's source code must be declared using the types "string" or "longstring"
typedef char string[maxStringLength + 1];
typedef char longstring[maxLongStringLength + 1];

// String length
extern int stringlen (const string src);
extern int lstringlen (const longstring src);

// String comparison - -1 for <, 0 for =, 1 for >
#define stringcmp(stringsrc1,stringsrc2)            strncmp(stringsrc1, stringsrc2, maxStringLength)
#define lstringcmp(lstringsrc1,lstringsrc2)         strncmp(lstringsrc1, lstringsrc2, maxLongStringLength)
#define stringncmp(stringsrc1,stringsrc2,length)    memcmp(stringsrc1, stringsrc2, length)
#define lstringncmp(lstringsrc1,lstringsrc2,length) memcmp(lstringsrc1, lstringsrc2, length)

// Safe string copy
extern void stringcpy (string dest, const string src);
extern void lstringcpy (longstring dest, const longstring src);

// Safe string concatenation
extern void stringcat (string dest, const string src);
extern void lstringcat (longstring dest, const longstring src);

// Safe sprintf 
#define stringprintf(dest, ...)                     snprintf (dest, maxStringLength, __VA_ARGS__) 
#define lstringprintf(dest, ...)                    snprintf (dest, maxLongStringLength, __VA_ARGS__) 

// Safe int-to-string and string-to-int, bases 10 and 16
extern void intstring (int value, int width, int base, string target);
#define lintstring(intval, width, base, longdest)   intstring (intval, width, base, longdest)
#define stringint(src)                              (strtol (src, NULL, 10))
#define lstringint(longsrc)                         stringint (longsrc)

// Safe real-to-string and string-to-real
#define realstring(realval, width, dest)            snprintf(dest, maxStringLength, "%.15g", realval)
#define lrealstring(realval, width, dest)           snprintf(dest, maxLongStringLength, "%.15g", realval)
#define stringreal(src)                             (strtod (src, NULL))
#define lstringreal(longsrc)                        stringreal (longsrc)

// Extended string operations

// String repeat - concatenate several copies of a string
extern void stringrep (string dest, const string src, const int n);
extern void lstringrep (longstring dest, const longstring src, const int n);

// Substring
extern void substring (string dest, const string src, const int lower, const int upper);
extern void lsubstring (longstring dest, const longstring src, const int lower, const int upper);

// String character - 1-origin 
#define stringchar(src, index)                      ((src)[(index) - 1])
#define lstringchar(src, index)                     ((src)[(index) - 1])

// String index - find the position of the first instance of a string in a string
extern int stringindex (const string src, const string pat);
extern int lstringindex (const longstring src, const longstring pat);

// Upper-to-lower and lower-to-upper case string maps 
extern void stringtolower (string srcdest); 
extern void stringtoupper (string srcdest);
extern void lstringtolower (longstring srcdest); 
extern void lstringtoupper (longstring srcdest);

// Undefine dangerous C string library so that we don't accidentally use it
#undef strcpy
#undef strcat
#undef sprintf
